package com.example.workflow.service.impl;

import com.example.workflow.dto.UpdatePassword;
import com.example.workflow.exception.ServiceException;
import com.example.workflow.flow.BizFlowTypeEnum;
import com.example.workflow.mapper.FormMapper;
import com.example.workflow.mapper.UserInfoMapper;
import com.example.workflow.pojo.LoginUser;
import com.example.workflow.pojo.Result;
import com.example.workflow.pojo.UserInfo;
import com.example.workflow.service.UserInfoService;
import com.example.workflow.util.FlowUtil;
import com.example.workflow.util.JwtUtil;
import com.example.workflow.util.RedisUtils;
import com.example.workflow.vo.LoginVo;
import com.example.workflow.vo.UserInfoVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.RuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.Flow;

import static com.example.workflow.pojo.Result.LOGIN_ERROR_CODE;
import static com.example.workflow.service.impl.FormServiceImpl.type_map;


@Service
@Slf4j
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private FormMapper formMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
//    private RedisCache redisCache;
    private RedisUtils redisUtils;


    /**
     * 登录操作
     *
     * @param userInfo 用户登录信息（用户名，密码）
     * @return Result
     */
    @Override
    public Result<String> login(UserInfo userInfo) {
        try
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userInfo.getName(), userInfo.getPassword());
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            if (Objects.isNull(authenticate)) {
                throw new RuntimeException("用户名或密码错误");
            }
            //使用userid生成token
            // 返回token
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            String userId = loginUser.getUserInfo().getId().toString();
            String jwt = JwtUtil.createJWT(userId);
            //authenticate存入redis
//            redisCache.setCacheObject("login:" + userId, loginUser);
//            redisCache.expire("login:"+userId, 3600*3600);
            ObjectMapper objectMapper=new ObjectMapper();
            redisUtils.set("login:"+userId,objectMapper.writeValueAsString(loginUser), 60 * 60 * 24 * 1000L);
            return Result.success(jwt);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(LOGIN_ERROR_CODE, "用户名或密码错误");
        }
    }

    /**
     * 用户登录
     *
     * @param userInfo 用户登录信息（用户名和密码）
     * @return 带有用户角色信息的 Result
     */
    @Override
    public Result<LoginVo> Login(UserInfo userInfo) {
        try
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userInfo.getName(), userInfo.getPassword());
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            if (Objects.isNull(authenticate)) {
                throw new RuntimeException("用户名或密码错误");
            }
            //使用userid生成token
            // 返回token
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            String userId = loginUser.getUserInfo().getId().toString();
            String jwt = JwtUtil.createJWT(userId);
            //authenticate存入redis
//            redisCache.setCacheObject("login:" + userId, loginUser);
//            redisCache.expire("login:"+userId, 3600*3600);
            ObjectMapper objectMapper=new ObjectMapper();
            redisUtils.set("login:"+userId,objectMapper.writeValueAsString(loginUser), 3600L *3600*3600);
            String role = loginUser.getUserInfo().getRole();
            role = switch (role) {
                case "ADMIN" -> "系统管理员";
                case "USER" -> "申请人员";
                case "CITY" -> "一级审批人员";
                case "PROVINCE" -> "二级审批人员";
                default -> "操作人员";
            };
            return Result.success(new LoginVo(role,jwt,loginUser.getUserInfo().getId().toString()));
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(LOGIN_ERROR_CODE, "用户名或密码错误");
        }
    }

    @Override
    public UserInfo getUserInfoByUserName(String userName) {
        return userInfoMapper.getUserInfoByUserName(userName);
    }

    /**
     * 用户注册
     *
     * @param userInfo 用户注册信息
     * @return 注册成功or失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int register(UserInfo userInfo) {
        if(userInfoMapper.getUserInfoByUserName(userInfo.getName())!=null) {
            throw new ServiceException("用户名已存在");
        }
        // 检查role和department是否为null
        if (userInfo.getRole() == null || userInfo.getDepartment() == null) {
            throw new ServiceException("角色或部门不能为空");
        }
        // 对密码进行编码
        userInfo.setPassword("111111");
        String encodedPassword = passwordEncoder.encode(userInfo.getPassword());
        userInfo.setPassword(encodedPassword);
        int userId = -1;

        try
        {
            int c =  userInfoMapper.register(userInfo);
            userId = userInfo.getId();

            /**
             * 新增部分
             *
             */
            switch (userInfo.getRole()) {
                case "CITY" -> {
                    List<String> types = type_map.get(userInfo.getDepartment());
                    List<Long> list = formMapper.listPrimary(types,"pending_l1");
                    // System.out.println(list);
                    for (Long orderId:list) {
//                        FlowUtil.printVariable(orderId.toString(),"cityUsers");
                        FlowUtil.updateVariable(BizFlowTypeEnum.ORDER_APPROVE.getKey(),orderId.toString(),"CITY",userId);
                    }

                }
                case "PROVINCE" -> {
                    List<String> types = type_map.get(userInfo.getDepartment());
                    List<Long> list = formMapper.listPrimary(types,"pending_l2");
                    for (Long orderId:list) {
//                        FlowUtil.printVariable(orderId.toString(),"provinceUsers");
                        FlowUtil.updateVariable(BizFlowTypeEnum.ORDER_APPROVE.getKey(),orderId.toString(),"PROVINCE",userId);

                    }
                }
                case "OPERATOR" -> {
                    List<String> types = type_map.get(userInfo.getDepartment());
                    List<Long> list = formMapper.getPrimary(types,userInfo.getDepartment());
                    for (Long orderId:list) {
                        FlowUtil.updateVariable(BizFlowTypeEnum.ORDER_APPROVE.getKey(),orderId.toString(),"OPERATOR",userId);
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return userId;
    }

    /**
     * 用户登出
     *
     * @return Result
     */
    @Override
    public Result<String> logout() {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            // 检查用户是否已认证（避免未登录时NPE）
            if (authentication == null || !authentication.isAuthenticated()) {
                throw new IllegalStateException("用户未登录");
            }
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            Integer userId = loginUser.getUserInfo().getId();
//            redisCache.deleteObject("login:" + userId);
            redisUtils.delete("login:"+userId);
            return Result.success("退出成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("退出失败");
        }
    }

    /**
     * 更改用户信息
     *
     * @param userInfo 用户信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(UserInfo userInfo) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 检查用户是否已认证（避免未登录时NPE）
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new IllegalStateException("用户未登录");
        }
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        Integer userId = loginUser.getUserInfo().getId();
        userInfo.setId(userId);
        userInfoMapper.update(userInfo);
    }

    /**
     * 更改用户密码
     *
     * @param updatePassword 更新密码（旧密码|新密码）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<String> updatePassword(UpdatePassword updatePassword) {
        try {
            Authentication authenticate = SecurityContextHolder.getContext().getAuthentication();
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            Integer userId = loginUser.getUserInfo().getId();
            updatePassword.setId(userId);

            String encodedPassword = passwordEncoder.encode(updatePassword.getNewPassword());
            updatePassword.setNewPassword(encodedPassword);
            userInfoMapper.updatePassword(updatePassword);
            return Result.success("修改密码成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("修改密码失败");
        }
    }

    /**
     * 删除用户
     *
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Integer id) {
        // 确保用户没有进行的工单
        Integer leave_orders = userInfoMapper.orderList(id),leave_workers=userInfoMapper.deptJudge(id);
        if(leave_orders!=0&&leave_workers<=1){
            throw new ServiceException("删除失败");
        }
        userInfoMapper.delete(id);
    }

    /**
     * 查找用户列表
     *
     * @return 查找信息
     */
    @Override
    public List<UserInfoVo> userList(Integer id,String name,String department,String role) {
        return userInfoMapper.userList(id,name,department,role);
    }

    /**
     * 根据工单信息查找创建者信息
     *
     * @param orderId 工单ID
     * @return 用户信息
     */
    @Override
    public UserInfo getUserInfoByOrder(Long orderId) {
        return userInfoMapper.getUserInfoByOrder(orderId);
    }

    /**
     * 根据用户ID列表批量查找用户信息
     *
     * @param userIds id列表
     * @return 用户信息列表 s
     */
    @Override
    public List<UserInfo> getUserInfoByIds(List<Integer> userIds) {
        return userInfoMapper.getUserInfoByIds(userIds);
    }

    /**
     * 根据用户id查找用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public UserInfo details(Integer userId) {
        return userInfoMapper.details(userId);
    }

    /**
     * 管理员修改用户信息
     *
     * @param userInfo 修改的用户信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modify(UserInfo userInfo) {
        userInfoMapper.modify(userInfo);
    }

    /**
     * 管理员重置用户密码
     *
     * @param id 用户id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reset(Integer id) {
        String encodedPassword = passwordEncoder.encode("111111");
        UpdatePassword updatePassword = new UpdatePassword();
        updatePassword.setId(id);
        updatePassword.setNewPassword(encodedPassword);
        userInfoMapper.updatePassword(updatePassword);
    }
}